﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ObjectDB.Library;

namespace ObjectDB.Testing
{
	/// <summary>
	/// Summary description for UnitTest1
	/// </summary>
	[TestClass]
	public class CecilTests
	{
		[TestMethod]
		public void Can_generate_assembly()
		{
			var assembly = new AssemblyGenerator("TestingDB").GenerateAssembly();

			Assert.IsNotNull(assembly);
			Assert.AreEqual("TestingDB", assembly.GetName().Name);
			Assert.IsNotNull(assembly.GetModule("MainModule"));
		}

		[TestMethod]
		public void Can_generate_class()
		{
			var assembly = new AssemblyGenerator("TestingDB")
				.DefineType("Name")
					.DefineConstructor()
					.DefineField<string>("First")
					.DefineField<string>("Middle")
					.DefineField<string>("Last")
					.GenerateType()
				.GenerateAssembly();

			var nameType = assembly.GetType("TestingDB.Name");
			Assert.IsNotNull(nameType);
			Assert.IsTrue(nameType.IsPublic);
			Assert.IsTrue(nameType.IsClass);
		}

		[TestMethod]
		public void Can_generate_fields()
		{
			var assembly = new AssemblyGenerator("TestingDB")
				.DefineType("Name")
					.DefineConstructor()
					.DefineField<string>("First")
					.DefineField<string>("Middle")
					.DefineField<string>("Last")
					.GenerateType()
				.GenerateAssembly();
			var nameType = assembly.GetType("TestingDB.Name");

			var firstField = nameType.GetField("First");
			var middleField = nameType.GetField("Middle");
			var lastField = nameType.GetField("Last");

			Assert.IsNotNull(firstField);
			Assert.IsTrue(firstField.IsPublic);
			Assert.AreEqual(typeof(string), firstField.FieldType);

			Assert.IsNotNull(middleField);
			Assert.IsTrue(middleField.IsPublic);
			Assert.AreEqual(typeof(string), middleField.FieldType);

			Assert.IsNotNull(lastField);
			Assert.IsTrue(lastField.IsPublic);
			Assert.AreEqual(typeof(string), lastField.FieldType);
		}

		[TestMethod]
		public void Can_use_type()
		{
			var assembly = new AssemblyGenerator("TestingDB")
				.DefineType("Name")
					.DefineConstructor()
					.DefineField<string>("First")
					.DefineField<string>("Middle")
					.DefineField<string>("Last")
					.GenerateType()
				.GenerateAssembly();
			var nameType = assembly.GetType("TestingDB.Name");

			dynamic name = Activator.CreateInstance(nameType);
			Assert.IsNotNull(name);

			name.First = "Billy";
			name.Middle = "Bob";
			name.Last = "Jones";

			Assert.AreEqual("Billy", name.First);
			Assert.AreEqual("Bob", name.Middle);
			Assert.AreEqual("Jones", name.Last);
		}

		[TestMethod]
		public void Can_persist_object()
		{
			var assembly = new AssemblyGenerator("TestingDB")
				.DefineType("Name")
					.DefineConstructor()
					.DefineField<string>("First")
					.DefineField<string>("Middle")
					.DefineField<string>("Last")
					//.DefineMethod("Power")
					.GenerateType()
				.GenerateAssembly();
			var nameType = assembly.GetType("TestingDB.Name");
			dynamic name = Activator.CreateInstance(nameType);
			name.First = "Billy";
			name.Middle = "Bob";
			name.Last = "Jones";

			var elem = Persister.Serialize(name);

			dynamic rename = Persister.Deserialize(elem, nameType);

			Assert.IsNotNull(rename);
			Assert.AreEqual("Billy", rename.First);
			Assert.AreEqual("Bob", rename.Middle);
			Assert.AreEqual("Jones", rename.Last);
		}
	}
}